<?php
/**
 * Tool SLS_Image - Image Treatment
 *  
 * @author Laurent Bientz 
 * @copyright SillySmart
 * @package Tools
 * @since 1.0 
 */ 
class SLS_Image
{
	private $_path = "";
	private $_size = "";
	private $_width = "";
	private $_height = "";
	private $_extension = "";
	private $_existed = false;
	private $_allowedExtensions = array(
										'jpg',
										'jpeg',
										'png',
										'gif',
										'xbm'
										);
	private $_infos 			= array(
										'path'=>'',
										'size'=>'',
										'width'=>'',
										'height'=>'',
										'extension'=>''
									  	);

	/**
	 * Constructor
	 * 
	 * @access public
	 * @param string $path image path
	 */
	public function __construct($path="")
	{
		$this->_path = realpath($path);		
		$php = get_loaded_extensions();
		if (!in_array('gd', $php))
				SLS_Tracing::addTrace(new Exception("You need PHP Extension : gd"));
		
		$this->initImgInfos();		
	}
	
	/**
	 * Get file image informations
	 *
	 * @access private
	 */
	private function initImgInfos()
	{
		if ($this->isValidImg())
		{
			$this->_existed = true;
			$this->_extension = pathinfo($this->_path,PATHINFO_EXTENSION);
			$this->_size = SLS_String::getFileSize($this->_path);
			$this->_width = array_shift(getimagesize($this->_path));
			$this->_height = array_shift(array_slice(getimagesize($this->_path),1,1));
			$this->_infos['path'] = $this->_path;
			$this->_infos['size'] = $this->_size;
			$this->_infos['width'] = $this->_width;
			$this->_infos['height'] = $this->_height;
			$this->_infos['extension'] = $this->_extension;
		}		
	}

	/**
	 * Check if is valid image	 
	 *
	 * @access private
	 * @return boolean true if yes, else false
	 */
	private function isValidImg()
	{
		// If file exists
		if (file_exists($this->_path) !== false)
		{				
			// If the extension is allowed
			if ($this->isValidExtension(pathinfo($this->_path,PATHINFO_EXTENSION)) && 
					$this->isValidSize(SLS_String::getFileSize($this->_path)) &&
					$this->isValidWidth(array_shift(getimagesize($this->_path))) &&
					$this->isValidHeight(array_shift(array_slice(getimagesize($this->_path),1,1))))
				return true;
		}
		return false;
	}

	/**
	 * Check if is valid extension
	 *
	 * @access private
	 * @param string $extension the extension to check
	 * @return boolean $valid true if yes, else false
	 */
	private function isValidExtension($extension)
	{
		$valid = false;

		foreach($this->_allowedExtensions as $value)
			if (strtolower($extension) == $value)
				$valid = true;
				
		return $valid;
	}	
	
	/**
	 * Check if file size is not null
	 *
	 * @access private
	 * @param string $size the size
	 * @return boolean true if yes, else false
	 */
	private function isValidSize($size)
	{
		if (!is_null($size) && !empty($size))
			return true;
		return false;
	}
	
	/**
	 * Check if width is valid
	 *
	 * @access private
	 * @param int $width the width
	 * @return boolean true if yes, else false
	 */
	private function isValidWidth($width)
	{
		if (!empty($width) && is_numeric($width))
			return true;
		return false;
	}

	/**
	 * Check if height is valid
	 *
	 * @access private
	 * @param int $width the height
	 * @return boolean true if yes, else false
	 */
	private function isValidHeight($height)
	{
		if (!empty($height) && is_numeric($height))
			return true;
		return false;
	}
	
	/**
	 * Getter of one param
	 *
	 * @access public
	 * @param string $param variable name
	 * @return string value if found, else empty
	 */
	public function getParam($param)
	{
		if ($this->isValidImg())
			return $this->{_.$param};
		else 
			return "";
	}
	
	/**
	 * Getters of all param
	 *
	 * @access public
	 * @return array associative array with all params
	 */
	public function getParams()
	{
		if ($this->isValidImg())
			return $this->_infos;
		else 
			return array();
	}

	/**
	 * Transform image
	 *
	 * @access public
	 * @param int $widthMax max wanted width
	 * @param int $heightMax max wanted height
	 * @param string $destination destination path (same with source path if is not filled)
	 * @param string $extensionWanted extension wanted (same with original if is not filled)
	 * @param string $quality quality wanted in the case of JPG file (0 : poor - 100 : best)
	 * @return boolean true if ok, else false
	 */
	public function transform($widthMax="", $heightMax="", $destination="", $extensionWanted="", $quality="100")
	{
		// If is valid image
		if ($this->isValidImg())
		{
			// If we haven't filled the destination, we fixed the same that source
			if (empty($destination))
				$destination = $this->_path;
			
			// We create images from starting extension			
			switch (strtolower($this->_extension))
			{
				case "jpg":		$source = ImageCreateFromJpeg($this->_path);	break;
				case "jpeg":  	$source = ImageCreateFromJpeg($this->_path);	break;			
				case "png":		$source = ImageCreateFromPng($this->_path);		break;
				case "gif":		$source = ImageCreateFromGif($this->_path);		break;			
				case "xbm":		$source = ImageCreateFromXbm($this->_path);		break;						
			}
			
			if ($source === false)
				return false;
				
			// Recover sources dimensions			
			$width_orig = $this->_width;
			$height_orig = $this->_height;

								
			// Calculate ratio
			if (empty($widthMax) && empty($heightMax))
			{
				$widthMax = $width_orig;
				$heightMax = $height_orig;
			}
			if (!empty($widthMax) || !empty($heightMax))
			{			
				if (empty($widthMax))
					$widthMax = ($heightMax / $height_orig) * $width_orig;
				else
					$heightMax = ($widthMax / $width_orig) * $height_orig;
			}						
			
			// We create new image in which we resample image
			$im = ImageCreateTrueColor($widthMax, $heightMax);
			
			if ($im === false)
				return false;
			else if(strtolower($this->_extension) == "png")
			{
				imagealphablending($im, false);
				imagesavealpha($im, true);
				imagecolortransparent($im);
			}
				
			$status = ImageCopyResampled($im, $source, 0, 0, 0, 0, $widthMax, $heightMax, $width_orig, $height_orig);
			if ($status === false)
				return false;
			
			// If we have filled a final extension and it exists			
			if (!empty($extensionWanted) && $this->isValidExtension($extensionWanted))
			{	
				switch (strtolower($extensionWanted))
				{
					case "jpg":		$result = ImageJpeg($im, $destination, $quality); 	break;
					case "jpeg":	$result = ImageJpeg($im, $destination, $quality); 	break;
					case "png":		$result = ImagePng($im, $destination); 				break;	
					case "gif":		$result = ImageGif($im, $destination);				break;			
					case "xbm":		$result = ImageXbm($im, $destination);				break;	
					default:		$result = ImageJpeg($im, $destination);				break;				
				}
			}
			// Else, keep the same extension			
			else 
			{
				switch (strtolower($this->_extension))
				{
					case "jpg":		$result = ImageJpeg($im, $destination, $quality); 	break;
					case "jpeg":	$result = ImageJpeg($im, $destination, $quality); 	break;
					case "png":		$result = ImagePng($im, $destination); 				break;	
					case "gif":		$result = ImageGif($im, $destination);				break;			
					case "xbm":		$result = ImageXbm($im, $destination);				break;		
					default:		$result = ImageJpeg($im, $destination);				break;					
				}
			}
			
			if ($result === false)
				return false;
			
			// Destroy image
			ImageDestroy($im);
			return true;
		}
		// If image isn't valid
		else 		
			return false;		
	}
	
	/**
	 * Try to move / rename image	 
	 *
	 * @access public
	 * @param string $destination destination path
	 * @return boolean true if moved, else false
	 */
	public function moveImage($destination)
	{	
		// If image is valid, try to move
		if ($this->isValidImg())		
			return rename($this->_path,$destination);
		
		// If image isn't valid
		else 		
			return false;		
	}
	
	/**
	 * Delete an image
	 *
	 * @access public
	 * @return boolean true if deleted, else false
	 */
	public function destroyImage()
	{
		// If image is valid, try to delete
		if ($this->isValidImg())		
			return unlink($this->_path);
	}
	
	/**
	 * Rotate an image
	 *
	 * @access public
	 * @param char $side rotation side 'r'|'l' ('r' if not filled)
	 * @param string $destination destination path (same with source path if is not filled)
	 * @return boolean true if rotated, else false
	 */
	public function rotateImage($side='r',$destination="")
	{
		// If image is valid, try to rotate
		if ($this->isValidImg())
		{
			// If we haven't filled the destination, we fixed the same that source
			if (empty($destination))
				$destination = $this->_path;
			
			// We create images from starting extension			
			switch (strtolower($this->_extension))
			{
				case "jpg":		$source = ImageCreateFromJpeg($this->_path);	break;
				case "jpeg":  	$source = ImageCreateFromJpeg($this->_path);	break;			
				case "png":		$source = ImageCreateFromPng($this->_path);		break;	
				case "gif":		$source = ImageCreateFromGif($this->_path);		break;			
				case "xbm":		$source = ImageCreateFromXbm($this->_path);		break;						
			}
			
			if ($source === false)
				return false;
			
			// We calculate degree to rotate
			if (strtolower($side) == 'l')			
				$degrees = 90;			
			else  
				$degrees = 270;
			
			// We rotate
			$rotate = imagerotate($source, $degrees, 0);
			
			if ($rotate === false)
				return false;
			
			// We save image
			switch (strtolower($extension))
			{
				case "jpg":		$result = ImageJpeg($rotate, $destination);	break;
				case "jpeg":	$result = ImageJpeg($rotate, $destination);	break;			
				case "png":		$result = ImagePng($rotate, $destination);	break;	
				case "gif":		$result = ImageGif($rotate, $destination);	break;			
				case "xbm":		$result = ImageXbm($rotate, $destination);	break;		
				default:		$result = ImageJpeg($rotate, $destination);	break;					
			}
			
			if ($result === false)
				return false;
			
			// Destroy image
			ImageDestroy($source);
			return true;
		}
		// If image isn't valid
		else 		
			return false;	
	}
}
?>